#include "TListE.h"
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
TListE::TListE():length(0), first(NULL) {}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
TListE::TListE(void *newElement) {

  first  = new TNode(newElement);
  length = 1;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
TListE::TListE(TListE * list) {

  int length = list->Length();

  if (!length) first = NULL;
  else {

    first         = new TNode(list->Get(0));
    TNode *cursor = first;

    for(int i = 1; i < length; i++) {
      TNode *newNode = new TNode(list->Get(i));
      cursor->Next(newNode);
      cursor = newNode;
    }

  }
}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
TListE::~TListE() {

  TNode *cursor;
  while(first) { cursor = first; first = first->Next(); delete cursor; }

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
TNode* TListE::PosNode(int pos) {

  TNode *cursor = first;
  for (int i = 0; i < pos; i++) cursor = cursor->Next();
  return cursor;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void TListE::Add(void* newElement) {

  TNode *newNode = new TNode(newElement);
  TNode *cursor   = first;

  if (first) {
    while (cursor->Next()) cursor = cursor->Next();
    cursor->Next(newNode);
  }
  else first = newNode;

  length++;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void TListE::Delete(int pos) {

  if ((pos < 0) || (pos >= length)) throw -1;

  TNode *cursor = first;

  if (!pos) first = first->Next();
  else {
    for (int i = 0; i < pos - 1; i++) cursor = cursor->Next();
    TNode *deleteNode = cursor->Next();
    cursor->Next(deleteNode->Next());
    cursor = deleteNode;
  }

  delete cursor;
  length--;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void TListE::Delete(void* value) {

  TNode *cursor = first, *temp = cursor;
  int pos = 0;

  while((cursor) && (cursor->Info() != value)) {
    temp   = cursor;
    cursor = cursor->Next();
    pos++;
  }

  if (!pos) first = first->Next();
  else temp->Next(cursor->Next());

  delete cursor;
  length--;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void* TListE::Transfer(int pos) {

  if ((pos < 0) || (pos >= length)) throw -1;

  TNode *cursor = first;

  if (!pos) first = first->Next();
  else {
    for (int i = 0; i < pos - 1; i++) cursor = cursor->Next();
    TNode *deleteNode = cursor->Next();
    cursor->Next(deleteNode->Next());
    cursor = deleteNode;
  }

  length--;
  return cursor->Info();

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void TListE::Insert(void* newElement, int pos) {

  if ((pos < 0) || (pos > length)) -1;

  TNode *newNode = new TNode(newElement);

  if (!pos) {
    newNode->Next(first);
    first = newNode;
  }
  else {
    TNodo *cursor  = first;
    int   count = 1;
    while (count < pos) { cursor = cursor->Next(); count++; }
    newNode->Next(cursor->Next());
    cursor->Next(newNode);
  }

  length++;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
bool TListE::Update(void* value, int pos) {
    
  if ((pos < 0) || (pos > length)) throw -1;
  
  Delete(pos);
  Insert(value, pos);
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void* TListE::Get(int pos) {

  if ((pos < 0) || (pos >= length)) throw -1;
  TNode* cursor = first;
  for (int i = 0; i < pos; i++) cursor = cursor->Next();
  return cursor->Info();

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void TListE::ForEach(TFunctionAction fAction, void *reference = NULL) {
    
  TNode* cursor = first;
  while (cursor) { fAction(cursor, reference); cursor = cursor->Next(); }
  
}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void* TListE::FirstSatisfy(TFunctionConditional fCondition, void *reference = NULL) {
    
  TNode* cursor = first;
  bool found = false;
  
  while (cursor && !found) {
    if (fCondition(cursor, reference)) found = true;
    else cursor = cursor->Next();
  }
  
  return ((found)? cursor->Info():NULL);

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void TListE::AllThatSatisfy(TFunctionConditional fCondition, TListE &ListT, void *reference = NULL) {
    
  TNode* cursor = first;
  if (ListT.Length())
    for (int i = 0; i < ListT.Length(); i++) ListT.Transfer(i);
    
  while (cursor) {
    if (fCondition(cursor, reference))
      ListT.Add(cursor->Info());
    cursor = cursor->Next();
  }
    
}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int TListE::HowManySatisfy(TFunctionConditional fCondition, void *reference = NULL) {
    
  TNode* cursor = first;
  int number  = 0;
  
  while (cursor) {
    if (fCondition(cursor, reference))
      number++;
    cursor = cursor->Next();
  }
  
  return number;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void TListE::OrderList(TFunctionConditional fCondition, void *reference = NULL) {
    
  for (int i = 0; i < length - 1; i++)
    for (int j = i + 1; j < length; j++)
      if (fCondition(PosNode(i), PosNode(j))) {
        if (i > j) {
           void* TempInfoI = Transfer(i);
           void* TempInfoJ = Transfer(j);
           Insert(TempInfoI, j);
           Insert(TempInfoJ, i);
        }
        else {
           void* TempInfoJ = Transfer(j);
           void* TempInfoI = Transfer(i);
           Insert(TempInfoJ, i);
           Insert(TempInfoI, j);
        }
      }
}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------

 